package nl.vu.few.ibivu.biomodels.client.ui;

import nl.vu.few.ibivu.biomodels.client.UniprotDataSource;
import nl.vu.few.ibivu.biomodels.client.ui.view.ComponentDetailsView;

import com.smartgwt.client.types.AutoFitWidthApproach;
import com.smartgwt.client.types.ExpansionMode;
import com.smartgwt.client.types.SelectionAppearance;
import com.smartgwt.client.types.SelectionStyle;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.Window;
import com.smartgwt.client.widgets.events.VisibilityChangedEvent;
import com.smartgwt.client.widgets.events.VisibilityChangedHandler;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.ButtonItem;
import com.smartgwt.client.widgets.form.fields.CheckboxItem;
import com.smartgwt.client.widgets.form.fields.TextItem;
import com.smartgwt.client.widgets.form.fields.events.ChangeEvent;
import com.smartgwt.client.widgets.form.fields.events.ChangeHandler;
import com.smartgwt.client.widgets.form.fields.events.ClickEvent;
import com.smartgwt.client.widgets.form.fields.events.ClickHandler;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.grid.events.SelectionChangedHandler;
import com.smartgwt.client.widgets.grid.events.SelectionEvent;
import com.smartgwt.client.widgets.layout.VLayout;

public class ComponentDetailsWindow extends Window implements ComponentDetailsView {

	private DynamicForm form;
	private TextItem nameText;
	private ButtonItem selectButton;
	private ButtonItem searchButton;
	private CheckboxItem unknownComponent;
	private ListGrid grid;
	private UniprotDataSource uniprotDS;
	private Presenter presenter;

	public ComponentDetailsWindow() {
		super();
		
		presenter = null;
		
		setAutoSize(true);
		setAutoCenter(true);
		setIsModal(true);
		setShowModalMask(true);
		setTitle("Gene Properties");
		setShowMinimizeButton(false);
		setShowCloseButton(false);

		VLayout vLayout = new VLayout();
		vLayout.setHeight100();
		vLayout.setWidth100();

		form = new DynamicForm();
		form.setAutoHeight();
		form.setWidth100();
		form.setPadding(5);
		form.setNumCols(3);

		nameText = new TextItem();
		nameText.setTitle("Gene/Protein Name");
		nameText.setRequired(true);
		nameText.setRequiredMessage("Please enter a name to identify your gene");
		
		
		searchButton = new ButtonItem();
		searchButton.setTitle("Search in Uniprot");
		searchButton.addClickHandler(new ClickHandler() {
					public void onClick(ClickEvent event) {
						if (form.validate()) {
							uniprotDS.setQuery(nameText.getValueAsString());
							grid.invalidateCache();
							grid.fetchData();
						}
					}
				});
		searchButton.setStartRow(false);
		searchButton.setEndRow(false);
		searchButton.setDisabled(true);
		
		selectButton = new ButtonItem();
		selectButton.setTitle("Select");
		selectButton.setStartRow(false);
		selectButton.setEndRow(false);
		selectButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				if (form.validate()) {
					ComponentDetailsWindow.this.hide();
					nameText.setValue("");
					grid.deselectAllRecords();
				}
			}
		});

		unknownComponent = new CheckboxItem();
		unknownComponent.setTitle("Choose from Uniprot");
		unknownComponent.setValue(false);
		unknownComponent.addChangeHandler(new ChangeHandler() {
			public void onChange(ChangeEvent event) {
				if (!(Boolean) event.getValue()) {
					nameText.setRequiredMessage("Please enter a name to identify your gene");
					searchButton.disable();
					selectButton.enable();
					grid.deselectAllRecords();
					grid.hide();
				} else {
					nameText.setRequiredMessage("Please enter the identifier to look for in Uniprot");
					searchButton.enable();
					selectButton.disable();
					grid.show();
				}
			}
		});

		form.setFields(nameText, selectButton, unknownComponent, searchButton);
		
		
		grid = new ListGrid() {

			@Override
			protected Canvas getExpansionComponent(ListGridRecord record) {
				String fullName = record.getAttributeAsString("fullName");
				if (fullName == null || fullName.isEmpty()) {
					record.setAttribute("fullName", "Description not available.");
				}
				return super.getExpansionComponent(record);
			}
			
		};
		grid.setVisible(false);
		grid.addSelectionChangedHandler(new SelectionChangedHandler() {

			@Override
			public void onSelectionChanged(SelectionEvent event) {
				ListGridRecord selected = event.getSelectedRecord();
				if (event.getSelectedRecord() == null) {
					nameText.setValue("");
					nameText.enable();
					if (unknownComponent.getValueAsBoolean()) {
						searchButton.enable();
						selectButton.disable();
					}
				}
				else {
					nameText.setValue(getName(selected) + "(" +	selected.getAttributeAsString("id") + ")");
					nameText.disable();
					searchButton.disable();
					selectButton.enable();
				}
			}
			
		});
		
		grid.setWidth(600);
		grid.setHeight(250);
		grid.setShowAllRecords(true);
		grid.setSelectionType(SelectionStyle.SINGLE);
		grid.setCanResizeFields(false);
		grid.setCanPickFields(false);
		grid.setCanReorderFields(false);
		grid.setAlternateRecordStyles(true);
		grid.setCanGroupBy(false);
		grid.setShowHeaderContextMenu(false);
		grid.setSelectionAppearance(SelectionAppearance.CHECKBOX);
		grid.setAutoFitWidthApproach(AutoFitWidthApproach.BOTH);
		grid.setAutoFitFieldWidths(true);
		grid.setAutoFitExpandField("organismName");
		grid.setAutoFitClipFields("geneName", "organismName");
		grid.setCanExpandRecords(true);
		grid.setExpansionMode(ExpansionMode.DETAIL_FIELD);
		grid.setDetailField("fullName");
		uniprotDS = new UniprotDataSource("ComponentSelectionUDS");
		grid.setDataSource(uniprotDS);
		
		vLayout.addMember(form);
		vLayout.addMember(grid);
		addItem(vLayout);
		
		addVisibilityChangedHandler(new VisibilityChangedHandler() {

			@Override
			public void onVisibilityChanged(VisibilityChangedEvent event) {
				if (!event.getIsVisible()) {
					ListGridRecord record = grid.getSelectedRecord();
					if (unknownComponent.getValueAsBoolean()) {
						if (record != null) {
							presenter.setUniprotId(record.getAttributeAsString("id"));
							presenter.setName(getName(record));
						}
					}
					else {
						presenter.setName(nameText.getValueAsString());
					}
					presenter.save();
				}
		}});
	}
	
	private String getName(ListGridRecord record) {
		String name = record.getAttributeAsString("geneName");
		if (name == null) {
			name = record.getAttributeAsString("id");
		}
		return name;
	}

	@Override
	public void setPresenter(Presenter presenter) {
		this.presenter = presenter;
		this.nameText.setValue(presenter.getName());
	}
}
